package com.cjk.console.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import com.cjk.console.enums.EventType;
import com.cjk.console.model.Channel;
import com.cjk.console.model.mqtt.ChannelMessage;
import com.cjk.console.request.ChannelRequest;
import com.cjk.foundation.commons.BusinessException;
import com.cjk.foundation.commons.response.PageResponse;
import com.cjk.foundation.commons.response.Response;
import com.cjk.foundation.dao.ChannelDao;
import com.cjk.foundation.dao.ChannelDetailDao;
import com.cjk.foundation.dao.DeviceDao;
import com.cjk.foundation.entity.ChannelDetailEntity;
import com.cjk.foundation.entity.ChannelEntity;
import com.cjk.foundation.enums.ConfStatus;
import com.cjk.foundation.enums.DeviceType;

@Service
public class ChannelServiceImpl implements ChannelService {
	
	@Autowired
	private ChannelDao channelDao;

	@Autowired
	private ChannelDetailDao channelDetailDao;
	
	@Autowired
	private DeviceDao deviceDao;
	
	@Value("${data.channel.path}")
	private String channelDataPath;
	
	@Autowired	
	private MqttService mqttService;
	
	@Transactional
	@Override
	public Response addChannel(ChannelRequest request, Integer userId) {
		channelDao.insert(request.getGroupId(), userId, ConfStatus.NOT_SYNC);
		String msg = "[";
		for (Channel channel : request.getChannels()) {
			if (channelDetailDao.selectByName(request.getGroupId(), channel.getName(), null) != null) {
				msg += channel.getName() + ", ";
				continue;
			}
			ChannelDetailEntity channelEntity = new ChannelDetailEntity();
			channelEntity.setGroupId(request.getGroupId());
			channelEntity.setName(channel.getName());
			channelEntity.setUrl(channel.getUrl());
			channelEntity.setPort(channel.getPort());
			channelEntity.setType("rtsp");
			channelDetailDao.insert(channelEntity);
		}
		if (!msg.equals("[")) {
			return Response.success(msg.substring(0, msg.length() - 2) + "]已经存在，添加失败");
		}
		return Response.success("添加成功");
	}

	@Override
	public PageResponse getChannelList(ChannelRequest request, Integer userId) {
		List<ChannelEntity> channelEntities = channelDao.selectListByCondition(userId, request.getPage(),
				request.getPageSize());
		if (CollectionUtils.isEmpty(channelEntities)) {
			return PageResponse.success(0, request.getPageSize(), new ArrayList<>());
		}
		for (ChannelEntity channelEntity : channelEntities) {
			channelEntity.setStatusDesc(channelEntity.getStatus().getLabel());
		}
		final Integer total = channelDao.selectCountByCondition(userId);
		return PageResponse.success(total, request.getPageSize(), channelEntities);
	}
	

	@Override
	public Response getChannelDetailList(ChannelRequest request, Integer userId) {
		List<ChannelDetailEntity> channelEntities = channelDetailDao.selectListByCondition(request.getGroupId(), null,
				null);
		return Response.success(channelEntities);
	}

	@Transactional
	@Override
	public Response editChannel(ChannelRequest request, Integer userId) {
		channelDao.insert(request.getGroupId(), userId, ConfStatus.NOT_SYNC);
		ChannelDetailEntity channelDetailEntity = channelDetailDao.selectByName(request.getGroupId(), request.getName(), request.getId());
		if (channelDetailEntity != null) {
			throw new BusinessException("频道已经存在");
		}
		ChannelDetailEntity updateChannelDetailEntity = new ChannelDetailEntity();
		updateChannelDetailEntity.setId(request.getId());
		updateChannelDetailEntity.setName(request.getName());
		updateChannelDetailEntity.setPort(request.getPort());
		updateChannelDetailEntity.setUrl(request.getUrl());
		channelDetailDao.update(updateChannelDetailEntity);
		return Response.success();
	}

	@Transactional
	@Override
	public Response delChannel(ChannelRequest request, Integer userId) {
		for (Integer id : request.getIds()) {
			channelDao.deleteByGroupId(id);
			channelDetailDao.deleteByGroupId(id);
		}
		return Response.success();
	}
	
	@Transactional
	@Override
	public Response delChannelDetail(ChannelRequest request, Integer userId) {
		channelDao.insert(request.getGroupId(), userId, ConfStatus.NOT_SYNC);
		channelDetailDao.deleteByIds(request.getGroupId(), request.getIds());
		return Response.success();
	}

	@Override
	public Response confChannel(ChannelRequest request, Integer userId) {
		Date date = new Date();
		for (Integer id : request.getIds()) {
			channelDao.conf(ConfStatus.UP_TO_DATE, date, id);
			ChannelEntity channelEntity = channelDao.selectByGroupId(id);
			List<ChannelDetailEntity> channelEntities = channelDetailDao.selectListByCondition(id, null, null);
			if (CollectionUtils.isEmpty(channelEntities)) {
				throw new BusinessException("存在分组未配置频道");
			}
			StringBuilder builder = new StringBuilder();
			for (ChannelDetailEntity channelDetailEntity : channelEntities) {
				builder.append(channelDetailEntity.getName() + " ");
				builder.append(channelDetailEntity.getType() + " ");
				builder.append(channelDetailEntity.getUrl() + " ");
				builder.append(channelDetailEntity.getPort());
				builder.append("\r\n");
			}
			File directory = new File(channelDataPath + "user_" + userId + "/group_" + id + "/");
			if (!directory.exists()) {
				directory.mkdirs();
			}
			String filePath = channelDataPath + "user_" + userId + "/group_" + id + "/iptv.conf";
			File file = new File(filePath);
			try {
				file.createNewFile();
				Writer write = new OutputStreamWriter(new FileOutputStream(file), "UTF-8");
				write.write(builder.toString());
				write.flush();
				write.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

			List<String> sns = deviceDao.selectSnsByGroupIdIncSub(id, DeviceType.SERVER);
			ChannelMessage channelMessage = new ChannelMessage();
			channelMessage.setEventType(EventType.CONFIG_TV);
			channelMessage.setPublishTime(new Date());
			channelMessage.setDownloadUrl("http://101.132.161.95/file/channel/" + channelEntity.getUserId() + "/" + id + "/iptv.conf");
			for (String sn : sns) {
				channelMessage.setSn(sn);
				mqttService.publish(sn, channelMessage);
			}		
		}
		return Response.success();
	}

	@Override
	public Response getChannel(Integer id) {
		ChannelDetailEntity channelEntity = channelDetailDao.selectById(id);
		return Response.success(channelEntity);
	}

}
